using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

using Pacman.Simulator;
using NeuralNetwork;

namespace Pacman.Implementations
{
	public class ShortestPac : BasePacman
	{

		public ShortestPac()
			: base("ShortestPac","1") {			
		}

		public override Direction Think( GameState gs ) {			
			// if this is to be used, probably make it a (faster) method on Map
			Node.PathInfo bestPath = null;
			Node bestNode = null;
			// hunt ghosts
			if( false ) {
				foreach( Pacman.Simulator.Ghosts.Ghost ghost in gs.Ghosts ) {
					if( !ghost.Chasing && ghost.RemainingFlee > 200 && ghost.Entered ) {
						Node.PathInfo curPath = gs.Pacman.Node.ShortestPath[ghost.Node.X, ghost.Node.Y];
						if( curPath != null && (bestPath == null || curPath.Distance < bestPath.Distance) ) {
							bestPath = curPath;
							bestNode = ghost.Node;
						}
					}
				}
			}
			// hunt pills
			if( bestPath == null ) {
				foreach( Node node in gs.Map.Nodes ) {
					if( node.Type != Node.NodeType.Wall ) {
						if( bestPath == null ) {
							bestNode = node;
							bestPath = gs.Pacman.Node.ShortestPath[node.X, node.Y];
							continue;
						}
						if( node.Type == Node.NodeType.Pill || node.Type == Node.NodeType.PowerPill ) {
							Node.PathInfo curPath = gs.Pacman.Node.ShortestPath[node.X, node.Y];
							if( curPath != null && curPath.Distance < bestPath.Distance ) {
								bestNode = node;
								bestPath = curPath;
							}
						}
					}
				}
			}
			// best direction			
			Direction dir = bestPath.Direction;
			// don't reverse in tunnels
			if( (gs.Pacman.Node.X < 4 || gs.Pacman.Node.X > Map.Width - 5) && gs.Map.Tunnels[gs.Pacman.Node.Y] && gs.Pacman.InverseDirection(gs.Pacman.Direction) == dir ) {			
				List<Direction> possible = gs.Pacman.PossibleDirections();
				int tries = 5;
				while( gs.Pacman.InverseDirection(gs.Pacman.Direction) == dir && tries > 0 ) {
					dir = possible[GameState.Random.Next(0, possible.Count - 1)];
					tries--;
				}
			}
			// avoid head on ghosts // buggy
			if( gs.Pacman.Node.ShortestPath[bestNode.X, bestNode.Y] != null ) {
				List<Node> bestRoute = gs.Map.GetRoute(gs.Pacman.Node.X, gs.Pacman.Node.Y, bestNode.X, bestNode.Y);
				for( int i = 0; i < 5 && i < bestRoute.Count; i++ ) {
					foreach( Pacman.Simulator.Ghosts.Ghost ghost in gs.Ghosts ) {
						if( ghost.Node == bestRoute[i] && ghost.Chasing ) {
							if( gs.Pacman.Direction == bestPath.Direction ) {
								dir = gs.Pacman.InverseDirection(gs.Pacman.Direction);
							} else {
								dir = gs.Pacman.Direction;
								List<Direction> possible = gs.Pacman.PossibleDirections();
								int tries = 5;								
								while( tries > 0 ) {
									Direction selection = possible[GameState.Random.Next(0, possible.Count - 1)];
									if( selection != gs.Pacman.InverseDirection(gs.Pacman.Direction) ){
										dir = selection;
										break;
									}
									tries--;
								}
							}
						}
					}
				}
			}
			// return best direction
			return dir;
		}
	}
}
